package com.sxpi.zixun.config.handler;

import com.sxpi.zixun.common.enums.AdminErrorResultEnum;
import com.sxpi.zixun.common.ex.ErrorHandler;
import com.sxpi.zixun.common.ex.PugBusinessException;
import com.sxpi.zixun.common.ex.PugOrderException;
import com.sxpi.zixun.common.ex.PugValidatorException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: 董伟豪
 * @Date: 2022/6/10 15:56
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 对所有异常进行捕获
     * 缺点：不明确
     * Throwable
   */
    @ExceptionHandler(Throwable.class)
    public ErrorHandler makeExcepton(Throwable e, HttpServletRequest request) {
        // 1: 一定要加下面这行代码。打印异常堆栈信息，方便程序员去根据异常排查错误 --服务开发者
        e.printStackTrace();
        // 2: 出现异常，统一返回固定的状态---服务用户
        ErrorHandler errorHandler = ErrorHandler.fail(AdminErrorResultEnum.SERVER_ERROR.getCode(),
                AdminErrorResultEnum.SERVER_ERROR.getMsg(), e);
        // 3: 最后返回
        return errorHandler;
    }

    /**
     * 对所有异常进行捕获
     * 缺点：不明确
     * RuntimeException
     */
    @ExceptionHandler(RuntimeException.class)
    public ErrorHandler makeExcepton2(RuntimeException e, HttpServletRequest request) {
        // 1: 一定要加下面这行代码。打印异常堆栈信息，方便程序员去根据异常排查错误 --服务开发者
        e.printStackTrace();
        // 2: 出现异常，统一返回固定的状态---服务用户
        ErrorHandler errorHandler = ErrorHandler.fail(AdminErrorResultEnum.SERVER_ERROR.getCode(),e.getMessage(), e);
        // 3: 最后返回
        return errorHandler;
    }


    /**
     * 对所有异常进行捕获
     * 缺点：不明确
     * RuntimeException
     */
    @ExceptionHandler(PugBusinessException.class)
    public ErrorHandler makeExcepton3(PugBusinessException e, HttpServletRequest request) {
        // 1: 一定要加下面这行代码。打印异常堆栈信息，方便程序员去根据异常排查错误 --服务开发者
        e.printStackTrace();
        // 2: 出现异常，统一返回固定的状态---服务用户
        ErrorHandler errorHandler = ErrorHandler.fail(e.getCode(),e.getMessage(), e);
        // 3: 最后返回
        return errorHandler;
    }


    /**
     * 对所有异常进行捕获
     * 缺点：不明确
     * RuntimeException
     */
    @ExceptionHandler(PugValidatorException.class)
    public ErrorHandler makeExcepton4(PugValidatorException e, HttpServletRequest request) {
        // 1: 一定要加下面这行代码。打印异常堆栈信息，方便程序员去根据异常排查错误 --服务开发者
        e.printStackTrace();
        // 2: 出现异常，统一返回固定的状态---服务用户
        ErrorHandler errorHandler = ErrorHandler.fail(e.getCode(),e.getMessage(), e);
        // 3: 最后返回
        return errorHandler;
    }

    /**
     * 对所有异常进行捕获
     * 缺点：不明确
     * RuntimeException
     */
    @ExceptionHandler(PugOrderException.class)
    public ErrorHandler makeExcepton5(PugOrderException e, HttpServletRequest request) {
        // 1: 一定要加下面这行代码。打印异常堆栈信息，方便程序员去根据异常排查错误 --服务开发者
        e.printStackTrace();
        // 2: 出现异常，统一返回固定的状态---服务用户
        ErrorHandler errorHandler = ErrorHandler.fail(e.getCode(),e.getMessage(), e);
        // 3: 最后返回
        return errorHandler;
    }

    /**
     * 对验证的统一异常进行统一处理  使用getFieldErrors的方式
     */
/*    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ErrorHandler handlerValiator(MethodArgumentNotValidException e, HttpServletRequest request) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<Map<String, String>> mapList = toValidatorMsg(fieldErrors);
        ErrorHandler errorHandler = ErrorHandler.fail(610, mapList, e);
        return errorHandler;
    }*/

    /**
     * 对验证的统一异常进行统一处理 使用getAllErrors的方式
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ErrorHandler handlerValiator(MethodArgumentNotValidException e, HttpServletRequest request) {
        List<ObjectError> fieldErrors = e.getBindingResult().getAllErrors();
        List<Map<String, String>> mapList = toValidatorMsg(fieldErrors);
        ErrorHandler errorHandler = ErrorHandler.fail(610, mapList, e);
        return errorHandler;
    }

    /**
     * 复杂的一个返回
     * @param fieldErrorList
     * @return
     */
    private List<Map<String, String>> toValidatorMsg(List<ObjectError> fieldErrorList) {
        List<Map<String, String>> mapList = new ArrayList<>();
        for (ObjectError fieldError : fieldErrorList) {
            DefaultMessageSourceResolvable defaultMessageSourceResolvable =
                    (DefaultMessageSourceResolvable) fieldError.getArguments()[0];
            String field = defaultMessageSourceResolvable.getDefaultMessage();
            if(StringUtils.isEmpty(field)){
                Map<String, String> map = new HashMap<>();
                map.put("field", "confirmPassword");
                map.put("msg", fieldError.getDefaultMessage());
                mapList.add(map);
            }else {
                // 这里考虑要不要增加过滤一下，一个个处理掉
                Long count = mapList.stream().filter(map -> map.get("field").equals(field)).count();
                if (count == 0L) {
                    Map<String, String> map = new HashMap<>();
                    map.put("field", field);
                    map.put("msg", fieldError.getDefaultMessage());
                    mapList.add(map);
                }
            }
        }
        return mapList;
    }

    /**
     * 对验证异常进行统一处理
     * 相同的属性只要一次，在不考虑校验密码和确定密码相等的时候用这个确实不错
     * @param fieldErrorList
     * @return
     */
    private List<Map<String, String>> toValidatorMsgMonomer(List<FieldError> fieldErrorList) {
        List<Map<String, String>> mapList = new ArrayList<>();
        for (FieldError fieldError : fieldErrorList) {
            long count = mapList.stream().filter(map -> map.get("field").equals(fieldError.getField())).count();
            if(count == 0L){
                Map<String, String> map = new HashMap<>();
                map.put("field", fieldError.getField());
                map.put("msg", fieldError.getDefaultMessage());
                mapList.add(map);
            }
        }
        return mapList;
    }

    /**
     * 对验证异常进行统一处理
     * 有多少错误返回多少错误到页面上
     * @param fieldErrorList
     * @return
     */
    private List<Map<String, String>> toValidatorMsgAll(List<FieldError> fieldErrorList) {
        List<Map<String, String>> mapList = new ArrayList<>();
        for (FieldError fieldError : fieldErrorList) {
            Map<String, String> map = new HashMap<>();
            map.put("field", fieldError.getField());
            map.put("msg", fieldError.getDefaultMessage());
            mapList.add(map);
        }
        return mapList;
    }


}
